<?php
/**
 * BAIR: BAtch Image Resizing library
 * 
 * Copyright (c) 2008 Daniel Cousineau
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @author Daniel Cousineau <dcousineau@gmail.com>
 * @version 2.0
 * @copyright 2008 Daniel Cousineau
 * @license MIT License http://www.opensource.org/licenses/mit-license.php
 * 
 * @package Bair
 */
class Bair
{
	const JPG = 'jpg';
	const GIF = 'gif';
	const PNG = 'png';
	
	protected $configurations = array();
	
	/**
	 * @var Bair_Engine_Interface
	 */
	protected $engine;
	
	public function __construct($engine, $config = null)
	{
		if( $engine instanceOf Bair_Engine_Interface )
			$this->setEngine($engine);
		elseif( class_exists('Bair_Engine_' . (string)$engine,true) )
		{
			$class = 'Bair_Engine_' . (string)$engine;
			$this->setEngine( new $class() );
		}
		else
		{
			throw new Bair_Exception("Invalid engine");
		}
		
		if( $config !== null && is_array($config) )
		{
			$this->_processConfig((array)$config);
		}
	}
	
	
	public function process($files)
	{
		if( count($this->configurations) < 1 )
			throw new Bair_Exception("At least 1 configuration is required");
		
		foreach( (array)$files as $file )
		{
			if( !is_readable($file) )
				throw new Bair_Exception("File '$file' cannot be read");
			
			foreach( $this->configurations as $key => $config )
			{
				$config->process($file);
			}
		}
		
		return true;
	}
	
	/**
	 * @param Bair_Engine_Interface $engine
	 * @return Bair Fluent Interface
	 */
	public function setEngine(Bair_Engine_Interface $engine)
	{
		$this->engine = $engine;
		return $this;
	}
	
	/**
	 * @return Bair_Engine_Interface
	 */
	public function getEngine()
	{
		return $this->engine;
	}
	
	/**
	 * @param string $name
	 * @param Bair_Config_Interface $config
	 * @return Bair Fluent Interface
	 */
	public function addConfig($name, Bair_Config_Interface $config)
	{
		$this->configurations[(string)$name] = $config;
		$config->setBair($this);
		return $this;
	}
	
	/**
	 * @param array $config
	 * @return Bair Fluent Interface
	 */
	public function addConfigs(array $config)
	{
		foreach( $config as $name => $obj )
		{
			$this->addConfig($name, $obj);
		}
		
		return $this;
	}
	
	/**
	 * @param string $name
	 * @return Bair_Config_Interface
	 */
	public function getConfig($name)
	{
		if( $this->configExists($name) )
			return $this->configurations[(string)$name];
		else
			throw new Bair_Exception("Config '$name' not found");
	}
	
	/**
	 * @return array Array of Bair_Config_Interface
	 */
	public function getConfigs()
	{
		return $this->configurations;
	}
	
	/**
	 * @param string $name
	 * @return bool
	 */
	public function configExists($name)
	{
		return isset($this->configurations[(string)$name]);
	}
	
	/**
	 * @param string $name
	 * @return bool
	 */
	public function removeConfig($name)
	{
		if( $this->configExists($name) )
		{
			unset($this->configurations[(string)$name]);
			return true;
		}
		else
			throw new Bair_Exception("Config '$name' not found");
	}
	
	/**
	 * Process array configuration. Keys are method names ('set'.$key) and their
	 * values are passed to said methods as arguments.
	 * 
	 * @param array $config
	 */
	protected function _processConfig(array $config)
	{
		foreach( $config as $setting => $values )
		{
			$method = 'set' . $setting;
			
			if( method_exists($this, $method) )
			{
				$reflMethod = new ReflectionMethod(__CLASS__, $method);
				$reflMethod->invokeArgs($this, $values);
			}
		}
	}
	
	/**
	 * Bair autoload function. Only checks this directory and only checks Bair classes
	 * 
	 * Bair plays nicely with Zend and other autoloaders so only use if you need to. 
	 * 
	 * Register using this line of code: spl_autoload_register(array('Bair','autoload'));
	 *
	 * @param string $classname
	 */
	public static function autoload($classname)
	{
		$file = dirname(__FILE__) . DIRECTORY_SEPARATOR . str_replace('_',DIRECTORY_SEPARATOR,$classname) . '.php';
		
		list($root) = explode('_', $classname);
		
		if( strtolower($root) === 'bair' && file_exists($file) )
		{
			include_once $file;
		}
	}
}